#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

//编译时 要是用 -pthread 选项
// gcc 10-pthread.c -o 10-pthread -pthread
#define N 128
char buf[N] = {0};
pthread_mutex_t mutex;
pthread_cond_t cond1, cond2, cond3;

void *pthread_handler1(void *arg)
{
    printf("arg1=%d\n", *(int *)arg);
    printf("1: pthread_handler is running\n");
    while (1)
    {
        pthread_mutex_lock(&mutex);// P操作
        pthread_cond_wait(&cond1, &mutex);
        pthread_mutex_unlock(&mutex);// V操作
        printf("pthread_handler1 is running\n");
    }
}

void *pthread_handler2(void *arg)
{
    printf("arg2=%d\n", *(int *)arg);
    printf("2: pthread_handler is running\n");
    while (1)
    {
        pthread_mutex_lock(&mutex);// P操作
        pthread_cond_wait(&cond2, &mutex);
        pthread_mutex_unlock(&mutex);// V操作
        printf("pthread_handler2 is running\n");
    }
}

void *pthread_handler3(void *arg)
{
    printf("arg3=%d\n", *(int *)arg);
    printf("3: pthread_handler is running\n");
    while (1)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond3, &mutex);
        pthread_mutex_unlock(&mutex);
        printf("pthread_handler3 is running\n");
    }
}

int main(int argc, char const *argv[])
{
    pthread_t tid1, tid2, tid3; // pthread id 线程 id
    int data1 = 100, data2 = 200, data3 = 300;

    int ret;
    
    // 锁被初始化后, 锁的状态是开的
    // pthread_lock 加锁后, 锁的状态是关闭状态
    // pthread_unlock 解锁后, 锁的状态是开的状态
    ret = pthread_mutex_init(&mutex, NULL);
    if (ret != 0)
    {
        printf("pthread_mutex_init error\n");
        exit(-1);
    }
    ret = pthread_cond_init(&cond1, NULL);
    if (ret != 0)
    {
        printf("pthread_mutex_init error\n");
        exit(-1);
    }
    ret = pthread_cond_init(&cond2, NULL);
    if (ret != 0)
    {
        printf("pthread_mutex_init error\n");
        exit(-1);
    }
    ret = pthread_cond_init(&cond3, NULL);
    if (ret != 0)
    {
        printf("pthread_mutex_init error\n");
        exit(-1);
    }
    //创建子线程1
    ret = pthread_create(&tid1, NULL, pthread_handler1, (void *)&data1);
    if (ret != 0)
    {
        printf("1: pthread_create eror\n");
    }

    //创建子线程2
    ret = pthread_create(&tid2, NULL, pthread_handler2, (void *)&data2);
    if (ret != 0)
    {
        printf("2: pthread_create eror\n");
    }

    //创建子线程3
    ret = pthread_create(&tid3, NULL, pthread_handler3, (void *)&data3);
    if (ret != 0)
    {
        printf("3: pthread_create eror\n");
    }

    printf("tid1=%ld\n", tid1);
    printf("tid2=%ld\n", tid2);
    printf("tid3=%ld\n", tid3);
    int num = 0;

    while (1)
    {
        printf("1: wakeup handler1 2: wakeup handler2 3:wakeup handler3 4:wakeup all\n");
            printf(">:");
        scanf("%d", &num);
        switch (num)
        {
        case 1:
            pthread_cond_signal(&cond1); //激活线程1
            break;
        case 2:
            pthread_cond_signal(&cond2); //激活线程2

            break;
        case 3:
            pthread_cond_signal(&cond3); //激活线程3

            break;
        case 4:
            pthread_cond_signal(&cond1); //激活线程1
            pthread_cond_signal(&cond2); //激活线程2
            pthread_cond_signal(&cond3); //激活线程3

            break;

        default:
            break;
        }
    }

    return 0;
}
